﻿using Panty;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace QFramework
{
    // 用于表现所有装备类型的枚举
    public enum E_EquipType : byte
    {
        Gun,    // 枪
        Sword,  // 剑
        Shield, // 盾
        Helmet, // 头盔
        Armor   // 护甲
    }
    // 用于 Json 加载的对象
    [Serializable]
    public class EquipJsonData<T> where T : EquipConfig
    {
        public T[] configs;
    }
    public interface IEquipConfigBuilder
    {
        List<EquipConfig> Builder();
    }
    // 用于创建子类实例的接口
    public interface IEquipConfig<T> where T : EquipInfo
    {
        T NewWeapon { get; }
    }
    public abstract class EquipConfig
    {
        [PnShowSprite]
        public Sprite sprite;
        public string Name;
    }
    public class SO_EquipConfig<T> : ScriptableObject, IEquipConfigBuilder where T : EquipConfig
    {
        [SerializeField] protected T[] configs;
        List<EquipConfig> IEquipConfigBuilder.Builder()
        {
            var list = new List<EquipConfig>(configs.Length);
            foreach (var config in configs) list.Add(config);
            return list;
        }
    }
    [Serializable]
    public class EquipInfo
    {
        public int ID;
        public string Name;
        public E_EquipType Type;
    }
    public interface IEquipmentFactorySystem : ISystem
    {
        /// <summary>
        /// 获取一件新装备
        /// </summary>
        /// <param name="type">装备类别</param>
        /// <param name="id">装备ID</param>
        /// <param name="info">新装备信息</param>
        /// <returns>是否获取成功</returns>
        bool CreateEquip<T>(E_EquipType type, int id, out T info) where T : EquipInfo;
        /// <summary>
        /// 获取一件新装备
        /// </summary>
        /// <param name="type">装备类别</param>
        /// <param name="id">装备ID</param>
        /// <param name="info">新装备信息</param>
        /// <returns>是否获取成功</returns>
        EquipInfo CreateEquip(E_EquipType type, int id);
        /// <summary>
        /// 创建所有装备
        /// </summary>
        /// <returns>装备列表</returns>
        List<EquipInfo> CreateAllEquip();
        /// <summary>
        /// 创建一个新的蓝图
        /// </summary>
        /// <param name="type">装备的类型</param>
        /// <param name="equip">具体装备</param>
        void CreateBlueprint(E_EquipType type, EquipConfig equip);
        /// <summary>
        /// 获取装备蓝图
        /// </summary>
        /// <typeparam name="T">装备配置类</typeparam>
        /// <param name="type">需要获取的装备类型</param>
        /// <param name="id">装备ID</param>
        /// <param name="config">装备配置信息</param>
        /// <returns>是否获取成功</returns>
        bool GetBlueprint<T>(E_EquipType type, int id, out T config) where T : EquipConfig;
    }
    public abstract class AbstractEquipmentFactorySystem : AbstractSystem, IEquipmentFactorySystem
    {
        private Dictionary<E_EquipType, List<EquipConfig>> mEquipConfigs;
        protected abstract EquipInfo CreateRules(E_EquipType type, EquipConfig equip);
        protected override void OnInit()
        {
            mEquipConfigs = new Dictionary<E_EquipType, List<EquipConfig>>();
        }
        List<EquipInfo> IEquipmentFactorySystem.CreateAllEquip()
        {
            var infos = new List<EquipInfo>();
            foreach (var configs in mEquipConfigs)
            {
                foreach (var config in configs.Value)
                {
                    var info = CreateRules(configs.Key, config);
                    if (info == null) continue;
                    infos.Add(info);
                }
            }
            return infos;
        }
        EquipInfo IEquipmentFactorySystem.CreateEquip(E_EquipType type, int id)
        {
            if (mEquipConfigs.TryGetValue(type, out var configs))
            {
                if (id >= 0 && id < configs.Count)
                {
                    return CreateRules(type, configs[id]);
                }
            }
            return null;
        }
        bool IEquipmentFactorySystem.CreateEquip<T>(E_EquipType type, int id, out T info)
        {
            if (mEquipConfigs.TryGetValue(type, out var configs))
            {
                if (id >= 0 && id < configs.Count)
                {
                    info = (configs[id] as IEquipConfig<T>).NewWeapon;
                    return true;
                }
            }
            info = null;
            return false;
        }
        void IEquipmentFactorySystem.CreateBlueprint(E_EquipType type, EquipConfig equip)
        {
            if (mEquipConfigs.TryGetValue(type, out var list)) list.Add(equip);
            else mEquipConfigs[type] = new List<EquipConfig>() { equip };
        }
        bool IEquipmentFactorySystem.GetBlueprint<T>(E_EquipType type, int id, out T config)
        {
            if (mEquipConfigs.TryGetValue(type, out var configs))
            {
                if (id >= 0 && id < configs.Count)
                {
                    config = configs[id] as T;
                    return true;
                }
            }
            config = null;
            return false;
        }
        protected void CreateFactoryBySO(string resPath, E_EquipType type)
        {
            mEquipConfigs[type] = (ResHelper.SyncLoad<ScriptableObject>(resPath) as IEquipConfigBuilder).Builder();
        }
        protected void CreateFactory<T>(string fileName, E_EquipType type) where T : EquipConfig
        {
            // 如果加载配置表成功 
            if (this.GetUtility<IJsonConfig>().Load<EquipJsonData<T>>(fileName, out var data))
            {
                if (data.configs == null || data.configs.Length == 0) return;
                var list = new List<EquipConfig>(data.configs.Length);
                foreach (var config in data.configs) list.Add(config);
                mEquipConfigs[type] = list;
            }
        }
        protected void CreateFactory<T>(E_EquipType type) where T : EquipConfig => CreateFactory<T>(typeof(T).Name, type);
    }
}